
#include "daq.h"

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <net/if.h>
#include <netdb.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#include "drv_packer.h"
#include "drv_server.h"


#define SEND_PACK_LEN 25000  // SEND num PER pack

uint32_t timestamp;

CMD_Packer net_packer;

int SAMPLE_RATE = (1 * 1000 * 1000);  // 1MHZ

uint8_t debug_on = 1;

int freq_div = 0;  // 1M

//采样状态
CAP_ACTION cap_action = STA_INIT;
CAP_ACTION last_cap_action = STA_INIT;
volatile uint32_t cap_len;
//采样使用的配置
CAP_PARAM cap_param;
//采样完成了保存数据的参数
CAP_PARAM save_param;
uint8_t is_sending = 0;
uint8_t hearthbeat_flag = 0;
uint8_t login_flag = 0;
uint8_t updatetime_flag = 0;
uint8_t start_code = 0;
uint8_t is_login = 0;
//是否获取到配置
uint8_t is_configed = 0;
LED_STATE led_state = LED_WAIT;
//发送缓存
uint8_t send_buff[102400] = {0};

uint32_t timer_login_cb(void *argument);
uint32_t timer_timestamp_cb(void *argument);
void print_ts_local(uint32_t ts);
void send_config_param();
uint8_t wait_data_ready();

char *server_id = "13\0";
char *server_key = "5e4af9297ea140e2941dc62897c5a8a8\0";

uint32_t get_ts() {
  struct timeval ts;
  gettimeofday(&ts, NULL);
  return ts.tv_sec;
}

void daq_init() {
  adc_init();
  SAMPLE_RATE = 1000000 / pow(2, freq_div);
  cap_param.div = freq_div;  //分频0-6，对应1M,/2/4
  cap_param.ch = 8;

  save_param.div = freq_div;
  // test cap data
  save_param.len = 1;
  save_param.start = 1539335694;
  save_param.ch = 8;

  DRV_PackerInit(&net_packer, ServerHandler, send_data);
}

/**
 * 处理采集任务
 */
void acquisition_process() {
  //已经获取到配置
  timestamp = get_ts();
  if (cap_action == STA_READY) {
    //时间至少是个有效值
    if (timestamp > 1539335694 && timestamp >= cap_param.start) {
      // start adc
      set_led(3, 1);
      cap_action = STA_RUNING;

      // //分频
      adc_write_reg(NO_OS | NO_STAND_BY | (freq_div << 2) |
                    ((cap_param.ch - 1) << 5));

      adc_set_num(cap_param.len * SAMPLE_RATE * cap_param.ch);
      adc_start(cap_param.len * SAMPLE_RATE * cap_param.ch);

      printf("adc start, cap len:%d s", cap_param.len);
      print_ts_local(timestamp);
    }
  } else if (cap_action == STA_RUNING) {
    // int status = AD7606_ReadStatus();
    if (g_waitFlag == false) {
      set_led(3, 0);
      cap_action = STA_STOP;
      save_param.len = cap_param.len;
      save_param.start = cap_param.start;
      save_param.div = freq_div;
      save_param.ch = cap_param.ch;
      printf("cap over !\n");
      print_ts_local(timestamp);
    }
  }
}

void daq_process() {
  if (net_status) {
    if (cap_action != last_cap_action) {
      last_cap_action = cap_action;
      send_config_param();
    }

    if (!is_login) {
      if (debug_on) {
        printf("Connect Server with id= %s\r\n", server_id);
      }
      //发送登录包
      LoginReq(&net_packer, (uint8_t *)server_id, strlen(server_id),
               (uint8_t *)server_key, strlen(server_key));
    }

  } else {
    is_login = 0;
  }

  // if (hearthbeat_flag) {
  // 	hearthbeat_flag = 0;
  // 	HearthBeatReq(&net_packer);
  // 	if (debug_on)
  // 		printf("Server HearthBeat Suc\r\n");
  // }

  if (updatetime_flag) {
    updatetime_flag = 0;
    //		mcu_get_ts();
  }
  //
  set_led(1, net_status);

  acquisition_process();
}

void print_ts_local(uint32_t ts) {
  struct tm *p;
  p = localtime((const time_t *)&ts);
  printf("Local Time: %02d-%02d-%02d %02d:%02d:%02d  \r\n", p->tm_year + 1900,
         p->tm_mon + 1, p->tm_mday, p->tm_hour + 8, p->tm_min, p->tm_sec);
}

void User_GroupReqHandler(uint8_t *body, uint16_t size) { return; };

//用户重写的服务器消息回调
void User_LoginHandler(uint8_t status) {
  if (status > 0) {
    is_login = 1;
    set_led(2, 1);
    printf("Server Login Suc\r\n");
    return;
  }
  set_led(2, 0);
  printf("Server Login Failed\r\n");

  return;
}

void User_DisconHandler(uint8_t status) {
  printf("Server Disocnnect \r\n");
  if (status > 0) {
    //成功
    // LED_SetFreq(1);
    set_led(2, 0);
    is_login = 0;
    return;
  }

  //失败后重启重连定时器
  printf("Tcp is Disocnnect failed\r\n");
  return;
}

/**
 * @brief  发送获取到的配置信息
 * @note
 * @retval None
 */
void send_config_param() {
  //上传采样控制参数+时间戳+当前状态
  uint32_t timestamp = get_ts();
  uint8_t buff[22];
  buff[0] = 0x82;
  memcpy(&buff[1], &cap_param, sizeof(cap_param));
  memcpy(&buff[17], &timestamp, sizeof(timestamp));
  ;
  buff[21] = cap_action;
  //发送数据
  GroupReq(&net_packer, buff, 22);
}

/**
 * @brief  获取采样保存的配置
 * @note
 * @retval None
 */
void send_save_param() {
  //获取已经采样得数据参数+时间戳+当前状态
  uint8_t buff[22];
  buff[0] = 0x83;
  uint32_t timestamp = get_ts();
  memcpy(&buff[1], &save_param, sizeof(save_param));
  memcpy(&buff[17], &timestamp, sizeof(timestamp));
  buff[21] = cap_action;
  //发送数据
  GroupReq(&net_packer, buff, 22);
}

void send_dbg_msg(char *msg, int size) {
  //获取已经采样得数据参数+时间戳+当前状态
  // uint8_t buff[256];
  send_buff[0] = 0x50;
  memcpy(&send_buff[1], msg, size);

  //发送数据
  GroupReq(&net_packer, send_buff, size + 1);
}

/**
 * @brief  发送某一个数据包
 * @note   每包1000 number，采样率1M每秒
 * @param  idx:
 * @retval None
 */
uint8_t send_data_pack(uint32_t idx, uint32_t all_idx) {
  // uint32_t all_idx =
  //     save_param.len * SAMPLE_RATE * save_param.ch / SEND_PACK_LEN;
  uint16_t *uhSdramArray = (uint16_t *)g_pAn706DataBufBase;
  // uhSdramArray += 1000;  //舍去前几个数据

  if (idx >= all_idx) {
    printf("UPLOAD Error idx of %d, all size %d\r\n", idx, all_idx);
    return 0;
  }
  // buff = (uint8_t *) malloc(1100);

  send_buff[0] = 0x84;

  memcpy(&send_buff[1], &idx, sizeof(idx));
  memcpy(&send_buff[5], &uhSdramArray[idx * SEND_PACK_LEN], SEND_PACK_LEN * 2);

  int send_len = SEND_PACK_LEN * 2 + 5;
  //发送数据
  GroupReq(&net_packer, send_buff, send_len);
  // free(buff);
  printf("Send Pack: idx %d,size %d\n", idx, send_len);

  return net_status;
}

/**
 * @brief  等待4g模块发送缓存空
 * @note
 * @retval
 */
uint8_t wait_data_ready() {
  //阻塞最长3秒
  uint32_t rx_length;
  uint32_t last_wake_time;
  char rx_buffer[21 + 1];

  //   last_wake_time = get_ts();  //获取当前tick，10ms

  //   while ((get_ts() - last_wake_time) < 10)  // 1000*10ms
  //   {
  //     /* 从串口读取数据*/
  //     rx_length = read(fduart1, rx_buffer, sizeof(rx_buffer));
  //     if (rx_length > 0) {
  //       rx_buffer[rx_length] = 0;
  //       if (strstr((char const *)rx_buffer, ">") != NULL) {
  //         return 1;
  //       }
  //     }
  //   }

  //   //超时
  //   printf("UPLOAD CAP DATA net over time\r\n");
  //   return 0;

  return 1;
}

/**
 * @brief  解析4g发过来得数据帧。
 * @note   已经建立在链路层通讯上
 * @param  *data:
 * @param  len:
 * @retval
 */
void User_P2pAndGroupHandler(uint8_t *data, uint16_t len) {
  printf("GET Msg Header: 0x%x, Size: %d\r\n", data[0], len);
  is_sending = 1;
  if (data[0] == 0x01) {
    //下发采样控制参数
    // copy出来数据
    if (len < 9) {
      printf("SET CAP PARAM Error Size\r\n");
      return;
    }
    //获取到设置参数
    {
      memcpy(&cap_param, &data[1], sizeof(cap_param));
      freq_div = cap_param.div;
      SAMPLE_RATE = 1000000 / pow(2, freq_div);
      cap_action = STA_READY;
      is_configed = 1;
      //   LED_SetFreq(5);

      if (cap_param.ch > 8) {
        cap_param.ch = 8;
      }

      //采样时间最长150M / 1M/ 8  = 18s
      if (cap_param.len > (AN706_SAMPLENUM / (SAMPLE_RATE * cap_param.ch))) {
        cap_param.len = 18;
      }
    }

    uint8_t buff[6];
    buff[0] = 0x81;

    //已经获取到时间
    uint32_t timestamp = get_ts();
    if (timestamp > 10000) {
      //返回成功和当前时间
      buff[1] = 0xdd;
      memcpy(&buff[2], &timestamp, sizeof(timestamp));
      GroupReq(&net_packer, buff, 6);
    } else {
      //失败
      buff[1] = 0xee;
      GroupReq(&net_packer, buff, 2);
    }
    printf("SET CAP PARAM: start at %d, len of %d, ts at %d, ", cap_param.start,
           cap_param.len, timestamp);
    print_ts_local(cap_param.start);

    send_config_param();
  } else if (data[0] == 0x02) {
    //上传采样控制参数+时间戳+当前状态
    send_config_param();
    uint32_t timestamp = get_ts();
    printf("UPLOAD CAP PARAM: start at %d, len of %d, ts at %d, ",
           cap_param.start, cap_param.len, timestamp);
    print_ts_local(cap_param.start);
  } else if (data[0] == 0x03) {
    //获取已经采样得数据参数+时间戳+当前状态
    send_save_param();
    uint32_t timestamp = get_ts();
    printf("UPLOAD SAVE PARAM: start at %d, len of %d, ts at %d, ",
           save_param.start, save_param.len, timestamp);
    print_ts_local(save_param.start);
  } else if (data[0] == 0x04) {
    //获取数据
    if (len != 9 && len != 5) {
      printf("GET CAP DATA Error Size\r\n");
      return;
    }
    //获取已经采样得数据参数+时间戳+当前状态
    send_save_param();
    uint32_t timestamp = get_ts();
    printf("UPLOAD SAVE PARAM: start at %d, len of %d, ts at %d, ",
           save_param.start, save_param.len, timestamp);
    print_ts_local(save_param.start);
    usleep(500 * 1000);

    // 0x04获取全部采样数据或者指定序号的数据包
    // 0x04 0x001 0x00 0x00 0x00
    //发送数据
    uint32_t idxstart = (data[1] & 0xff) | (data[2] & 0xff) << 8 |
                        (data[3] & 0xff) << 16 | (data[4] & 0xff) << 24;
    //一秒20包，40000字节, 每包长度2000
    uint32_t all_idx =
        save_param.len * SAMPLE_RATE * save_param.ch / SEND_PACK_LEN;

    if (idxstart != 0xffffffff && idxstart < all_idx) {
      //发送某一段包
      uint32_t idxend = (data[5] & 0xff) | (data[6] & 0xff) << 8 |
                        (data[7] & 0xff) << 16 | (data[8] & 0xff) << 24;
      printf("GET CAP DATA, idx from %d to %d\r\n", idxstart, idxend);

      if (idxend >= all_idx) {
        printf("GET CAP DATA Failed, error index\r\n");
        return;
      }
      for (uint32_t ii = idxstart; ii <= idxend; ii++) {
        send_data_pack(ii, all_idx);

        printf("UPLOAD Band DATA, idx of %d, all size %d\r\n", ii, all_idx);
      }
    } else {
      printf("GET ALL CAP DATA, PACK NUM=%d\r\n", all_idx);

      //发送全部数据
      for (uint32_t jj = 0; jj < all_idx; jj++) {
        if (send_data_pack(jj, all_idx) < 1) break;
      }
    }
  } else if (data[0] == 0x10) {
    //    //固件更新服务，获取固件版本
    //    //这个是boot分区的
    //    uint8_t *boot_buff;
    //    boot_buff = (uint8_t *)rt_malloc(260);
    //
    //    //boot分区,前256字节保存APP固件信息
    //    //检查boot分区当前app信息
    //
    //    fal_partition_read(boot_partition, 0, boot_buff, 260);
    //
    //    if (strlen(boot_buff + 64) > 60)
    //    {
    //      memcpy(boot_buff + 64, "NON\0", 4);
    //    }
    //    uint8_t buff[64];
    //    buff[0] = 0x91;
    //    strcpy(&buff[1], boot_buff + 64);
    //
    //    //发送数据
    //    GroupReq(&net_packer, buff, strlen(boot_buff + 64) + 1);
    //    printf("Send Firmware Boot Version: %s", boot_buff + 64);
    //    rt_free(boot_buff);
  } else if (data[0] == 0x11) {
    //    //固件更新服务，固件头信息
    //    //比较一下收到的和运行是否相同
    //    uint8_t header[64];
    //
    //    memset(header, 0, 64);
    //    memcpy(&recv_fw_size, data + 1, 4);
    //    memcpy(header, data + 5, len - 5);
    //
    //    //这个是boot分区的
    //    uint8_t *boot_buff;
    //    boot_buff = (uint8_t *)rt_malloc(260);
    //
    //    //boot分区,前256字节保存APP固件信息
    //    //检查boot分区当前app信息
    //
    //    fal_partition_read(boot_partition, 0, boot_buff, 260);
    //
    //    //比较固件版本名称
    //    if (memcmp(boot_buff + 64, header, 64) != 0)
    //    {
    //      printf("New version firmware find: %s, size:%d", header,
    //      recv_fw_size);
    //      //new version
    //      //start update
    //
    //      /* erase DL section */
    //      if (fal_partition_erase(dl_part, 0, recv_fw_size) < 0)
    //      {
    //        printf("Firmware download failed! Partition (%s) erase error!",
    //        dl_part->name); return;
    //      }
    //      //请求固件
    //      uint8_t buff[64];
    //      buff[0] = 0x92;
    //
    //      //发送数据
    //      GroupReq(&net_packer, buff, 1);
    //      printf("Request Firmware");
    //    }
  } else if (data[0] == 0x12) {
    //    int offset = 0;
    //    memcpy(&offset, data + 1, 4);
    //
    //    //固件更新服务，固件数据段
    //    if (fal_partition_write(dl_part, offset, data + 5, len - 5) < 0)
    //    {
    //      printf("Firmware download failed! Partition (%s) write data error!",
    //      dl_part->name); return;
    //    }
    //    printf("fw recv, offset:%d, len: %d", offset, len - 5);
    //
    //    if (recv_fw_size == (offset + len - 5))
    //    {
    //
    //      //下载完整
    //      uint8_t buff[64];
    //      buff[0] = 0x93;
    //
    //      //发送数据
    //      GroupReq(&net_packer, buff, 1);
    //
    //      printf("recv fw over, reboot now");
    //      rt_thread_delay(rt_tick_from_millisecond(200));
    //
    //      /* Reset the device, Start new firmware */
    //      extern void rt_hw_cpu_reset(void);
    //      rt_hw_cpu_reset();
    //      /* wait some time for terminal response finish */
    //      rt_thread_delay(rt_tick_from_millisecond(200));
    //    }
  } else if (data[0] == 0x13) {
    //    //远程复位重启
    //		 printf("recv reboot cmd, reboot now");
    //		 usleep(200*1000);
    //
    //     /* Reset the device, Start new firmware */
    //     extern void rt_hw_cpu_reset(void);
    //     rt_hw_cpu_reset();
    //      /* wait some time for terminal response finish */
    //     usleep(200*1000);
  } else if (data[0] == 0xee) {
    //失败
  } else if (data[0] == 0xdd) {
    //成功
  } else if (data[0] == 0x50) {
    //时间
    // get ts
    memcpy(&timestamp, data + 1, 4);

    struct timeval time_tv;
    time_tv.tv_sec = timestamp;
    time_tv.tv_usec = 0;

    int ret = settimeofday(&time_tv, NULL);
    if (ret != 0) {
      fprintf(stderr, "settimeofday failed\n");
    }
    printf("got time:%u\n", timestamp);
  } else {
    printf("GET Msg Error Proc\r\n");
  }
  is_sending = 0;
  return;
}
